package com.chujian.framework.wssync;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import com.chujian.framework.ws.IWsRcvMsgHandler;
import com.chujian.framework.ws.WsMsg;
import com.chujian.framework.ws.support.rcv.IWsDbStoreService;
import com.chujian.framework.ws.support.rcv.RcvMsgRespHandler;
import com.chujian.framework.ws.support.rcv.RcvMsgSaveDbHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.OrderComparator;
import org.springframework.lang.Nullable;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

@Slf4j
public class WsSyncRcver implements IWsSyncRcver, InitializingBean, ApplicationContextAware {

    private final List<IWsRcvMsgHandler> rcvMsgHandlerList = new ArrayList<>();
    private ApplicationContext ctx;

    private final RcvMsgRespHandler rcvMsgRespHandler;
    private final RcvMsgSaveDbHandler rcvMsgSaveDbHandler;
    private final IWsDbStoreService wsDbStore;

    public WsSyncRcver(RcvMsgRespHandler rcvMsgRespHandler,
                       RcvMsgSaveDbHandler rcvMsgSaveDbHandler,
                       @Nullable IWsDbStoreService wsDbStore) {
        this.rcvMsgRespHandler = rcvMsgRespHandler;
        this.rcvMsgSaveDbHandler = rcvMsgSaveDbHandler;
        this.wsDbStore = wsDbStore;
    }

    @Override
    public void onRcv(WsMsg msg, String payload) {
        log.debug("WsSyncRcver 接收消息. dataId：{} dataMark:{}", msg.getDataId(), msg.getDataMark());

        // 总是保存数据库
        if (!msg.isRetry()) {
            rcvMsgSaveDbHandler.handle(msg, payload);
        }

        IWsRcvMsgHandler handler = CollUtil.findOne(rcvMsgHandlerList, h -> h.canHandle(msg, payload));
        if (null == handler) {
            log.warn("未找到同步数据处理器. dataId：{} dataMark:{}", msg.getDataId(), msg.getDataMark());
            // 标记为已处理
            if (null != wsDbStore) {
                wsDbStore.markRcvSuc(msg);
            }
            return;
        }

        // 入队处理，成功加入等待队列，先不处理
        if (handler instanceof IWsSyncRcvMsgHandler && ((IWsSyncRcvMsgHandler) handler).enqueue(msg)) {
            return;
        }

        boolean suc = true;
        String errorMsg = null;
        try {
            // 直接处理
            handler.handle(msg, payload);
        } catch (Exception e) {
            suc = false;
            errorMsg = ExceptionUtil.stacktraceToString(e, 2000);
            log.error("同步消息消费失败, dataId：{} dataMark:{}", msg.getDataId(), msg.getDataMark(), e);
        }

        // 成功消费
        if (null != wsDbStore) {
            if (suc) {
                wsDbStore.markRcvSuc(msg);
            } else { // 消费失败
                wsDbStore.markRcvFailure(msg, errorMsg);
            }
        }

    }

    @Override
    public void afterPropertiesSet() throws Exception {
        // 通用处理器
        rcvMsgHandlerList.add(rcvMsgRespHandler);
        // rcvMsgHandlerList.add(rcvMsgSaveDbHandler);

        // ws同步消息接收处理器
        Collection<IWsSyncRcvMsgHandler> handlers = ctx.getBeansOfType(IWsSyncRcvMsgHandler.class).values();
        rcvMsgHandlerList.addAll(handlers);
        // 排序
        rcvMsgHandlerList.sort(OrderComparator.INSTANCE);

        for (IWsRcvMsgHandler handler : rcvMsgHandlerList) {
            log.info("装配ws同步接收消息处理器：{}", handler.getClass().getName());
        }

    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.ctx = applicationContext;
    }

    public List<IWsRcvMsgHandler> getRcvMsgHandlerList() {
        return rcvMsgHandlerList;
    }
}
